<template>
  <!--
-->
  <div :class="{ 'table-div': autoFlex, 'ex_table_auto_div': true }" v-loading="gridIsLoading"
    element-loading-text="拼命加载中" element-loading-background="rgba(255,255,255,0.8)">
    <el-table :ref="refId" :data="gridData" v-if="tableVisible" v-bind="_tableBind()" v-on="$listeners"
      @current-change="tableCurrentChange" @sort-change="sortChange"
      :class="{ 'table-flex': autoFlex, 'ex_table_auto': true }">
      <slot></slot>


      <template slot="empty" v-if="emptySlot">
        <slot name="empty">
          <div style="line-height: 32px; margin-bottom: 10px; margin-top: 10px;">
            <img src="../img/empty.png" style="height: 100px;" />
            <br />
            <font>{{ emptyTextDefine }}</font>
          </div>
        </slot>
      </template>



    </el-table>

    <el-pagination ref="pagination" v-if="simplePage" @size-change="handleSizeChange" background
      @current-change="handleCurrentChange" :current-page="pageParam.pageIndex" :page-size="pageParam.pageSize"
      :total="pageParam.totalSize" layout="total, prev, next"
      style="text-align: right; background-color: #fff; border: none;">
    </el-pagination>

    <el-pagination ref="pagination" v-if="!simplePage && autoPage" @size-change="handleSizeChange" background
      @current-change="handleCurrentChange" :current-page="pageParam.pageIndex" :page-size="pageParam.pageSize"
      :total="pageParam.totalSize" :page-sizes="[10, 20, 50, 100, 200, 500]"
      layout="total, sizes, prev, pager, next, jumper">

    </el-pagination>


  </div>
</template>

<script>
export default {
  data() {
    return {

      tableCurrentRow: {},

      gridIsLoading: false,
      refId: 'el-table-ref',

      pageParam: {
        totalSize: 0, // 总数据量
        pageIndex: 1, // 当前第几页
        pageSize: this.defaultPageSize // 每页多少条
      },
      gridData: [],
      emptyTextDefine: '暂无数据',


      caculateTableHeight: -1,
      lastRequestParam: {},

      willDoLayout: false,
      headerResizeObserver: null,
    }
  },
  created() {
    if (this.data && this.data.length > 0) {
      this.gridData = this.data
      return
    }
  },

  mounted() {
    if (typeof(ResizeObserver) === 'function' && /native code/.test(ResizeObserver.toString())) {
      this.headerResizeObserver = new ResizeObserver(entries => {
        this.willDoLayout = true
      })
    }


    this.$nextTick(() => {
      if (this.autoLoad) {
        this.loadData()
      }
      this.autoResizeHeight()

      this.headerResizeObserverBind()
    })
  },


  watch: {

    'url': function (val, old) {
      if (this.autoLoad) {
        this.loadData()
      }
    },

    'data': function (val, old) {
      this.gridData = val
    },
    'willDoLayout': function (val, old) {
      if (val) {

        this.willDoLayout = false
        this.$nextTick(() => {
          this.fixedToDoLayout()
        })
      }
    },
    'tableVisible': function (val, old) {
      if (val) {
        this.$nextTick(() => {
          this.headerResizeObserverBind()
        })
      }
    },
  },


  methods: {
    headerResizeObserverBind() {
      if (this.headerResizeObserver) {
        const header_wrapper = this.$refs[this.refId].$el.querySelector(".el-table__header-wrapper")
        if (header_wrapper) {
          this.headerResizeObserver.unobserve(header_wrapper);
          this.headerResizeObserver.observe(header_wrapper);
        }
      }
    },
    fixedToDoLayout() {
      const fixed_body_wrap = this.$refs[this.refId].$el.querySelector(".el-table__fixed-body-wrapper")
      if (fixed_body_wrap) {
        this.doLayout()
      }
    },
    getHeight() {
      return this.caculateTableHeight
    },

    autoResizeHeight() {

      let offset = 10
      // table 距离浏览器顶部距离

      if (!this.$el) {
        return
      }



      if (this.autoFill) {
        let tableTop = this.$el.getBoundingClientRect().top

        let windowHeight = window.innerHeight
        if (this.autoPage) {

          // ! 视觉改造之后，页面的底部有 16px 的高度，通过取翻页的高度来判断修复这个值，主要是为了兼容视觉改造和未改造两个版本的代码
          const fixedBottomHeight = this.$refs.pagination.$el.offsetHeight <= 30 ? 6 : 0
          const pagingBarheight = 64 - 16 + offset - fixedBottomHeight
          this.caculateTableHeight = windowHeight - tableTop - pagingBarheight
        } else {
          this.caculateTableHeight = windowHeight - tableTop - offset
        }
      } else {
        if (this.height) {
          this.caculateTableHeight = this.height
        } else {
          this.caculateTableHeight = undefined
        }
      }

    },

    setHeight(height) {
      this.caculateTableHeight = height
    },
    //内部维护选择的行数据
    tableCurrentChange(row) {

      this.tableCurrentRow = row

      this.$emit('current-change', row)
    },
    getCurrentRow() {
      return this.tableCurrentRow
    },
    getSelection() {
      return this.$refs[this.refId].selection
    },
    /* 原生方法传递 */
    doLayout() {
      if (this.$refs[this.refId]) this.$refs[this.refId].doLayout()
    },
    setCurrentRow(row, expanded) {
      this.$refs[this.refId].setCurrentRow(row, expanded)
    },
    clearSelection() {
      this.$refs[this.refId].clearSelection()
    },

    toggleRowSelection(row, selected) {
      this.$refs[this.refId].toggleRowSelection(row, selected)
    },
    toggleRowExpansion(row, selected) {
      this.$refs[this.refId].toggleRowExpansion(row, selected)
    },
    toggleAllSelection() {
      this.$refs[this.refId].toggleAllSelection()
    },
    sort(column, type) {
      this.$refs[this.refId].sort(column, type)
    },

    clearSort() {
      this.$refs[this.refId].clearSort()
    },


    sortChange(sortObj) {
      var order = sortObj.order
      var prop = sortObj.prop

      var lastParam = this.getLastRequestParam()

      lastParam.pageIndex = 1
      if (order && prop) {
        if (order == 'ascending') {
          lastParam.orderby = prop
        } else {
          lastParam.orderby = '-' + prop
        }
      }

      this.loadData(lastParam)
    },
    getDataLengh() {
      if (this.gridData) {
        return this.gridData.length
      }
      return 0
    },
    getData() {
      return this.gridData
    },

    setData(gridData) {
      this.gridData = gridData
      for (var i = 0; i < this.gridData.length; i++) {
        if (this.gridData[i]) {
          this.gridData[i][this.rowIndexField] = i
        }
      }

      this.$emit('grid-data-change', this.gridData)
    },

    resort() {
      for (var i = 0, len = this.gridData.length; i < len; i++) {
        if (this.gridData[i]) {
          this.gridData[i][this.rowIndexField] = i
        }
      }
      this.$emit('grid-data-change', this.gridData)
    },

    loadDataByUrl(apiUrl) {
      this.loadData(undefined, apiUrl)
    },

    getLastRequestParam() {
      return this.lastRequestParam
    },
    loadData(searchInputParams, newUrl, callback) {

      return new Promise((resolve, reject) => {
        let targetUrl = this.url

        if (newUrl) {
          targetUrl = newUrl
        }
        if (targetUrl && targetUrl != '') {


          // 提交到后台的查询参数
          let loadParam = {}
          // 点击查询按钮时，searchInputParams 不为空

          if (searchInputParams) {
            // 页码跳到第一页
            this.pageParam.pageIndex = 1

            this.lastRequestParam = _.cloneDeep(searchInputParams)
          }
          if (this.lastRequestParam) {
            for (let key in this.lastRequestParam) {
              loadParam[key] = this.lastRequestParam[key]
            }
          }



          if (this.urlParams instanceof Function) {
            loadParam = this.urlParams(loadParam)
          } else {
            loadParam = Object.assign(loadParam, this.urlParams)
          }

          // 填充分页参数
          if (this.autoPage) {
            loadParam.pageIndex = this.pageParam.pageIndex
            loadParam.pageSize = this.pageParam.pageSize

            this.lastRequestParam.pageIndex = this.pageParam.pageIndex
            this.lastRequestParam.pageSize = this.pageParam.pageSize
          }
          // 如果没有排充参数， 并且定义 gird 时设置了默认排序参数
          if (!loadParam.orderby && this.defaultSortColumn !== '_blank_') {
            loadParam.orderby = this.defaultSortColumn
          }


          // 开启蒙板
          this.gridIsLoading = true
          this.emptyTextDefine = '  '

          this.$ajax({
            url: targetUrl,
            method: 'post',
            ...this.urlOption,
            data: loadParam,
            success: (responseData) => {

              let _temp_list = this.urlDataHandle ? this.urlDataHandle(responseData) : responseData.data && responseData.data.rows || []
              _temp_list.map((it, index) => {
                it[this.rowIndexField] = index
              })
              this.gridData = _temp_list
              if (this.autoPage) {
                if (responseData.data && responseData.data.totalSize != undefined) {
                  this.pageParam.totalSize = responseData.data.totalSize
                } else {
                  this.pageParam.totalSize = 0
                }
                if (responseData.data && responseData.data.pageIndex != undefined) this.pageParam.pageIndex = responseData.data.pageIndex
                if (responseData.data && responseData.data.pageSize != undefined) this.pageParam.pageSize = responseData.data.pageSize
              }

              if (this.emptyText) {
                this.emptyTextDefine = this.emptyText
              } else {
                this.emptyTextDefine = this.$tt('tip_no_data')
              }

              let requestTotalSize = 0
              if (responseData.data && responseData.data.totalSize) {
                requestTotalSize = responseData.data.totalSize
              }
              else {
                if (responseData.data && responseData.data.rows && responseData.data.rows.length > 0) {
                  requestTotalSize = responseData.data.rows.length
                }
              }

              this.$emit('grid-data-change', this.gridData, this.lastRequestParam, requestTotalSize)

              if (callback) callback(responseData)
            },
            complete: () => {
              this.gridIsLoading = false
              this.$emit('grid-load-done')
            }
          })
        }
      })

    },
    handleSizeChange(newPageSize) {
      if (this.pageChangeBefore) {
        this.pageChangeBefore(() => {
          this.pageParam.pageIndex = 1
          this.pageParam.pageSize = newPageSize
          this.loadData()
        })
      } else {
        this.pageParam.pageIndex = 1
        this.pageParam.pageSize = newPageSize
        this.loadData()
      }

    },
    handleCurrentChange(pageIndexIndex) {
      if (this.pageChangeBefore) {
        this.pageChangeBefore(() => {
          this.pageParam.pageIndex = pageIndexIndex
          this.loadData()
        })
      } else {
        this.pageParam.pageIndex = pageIndexIndex
        this.loadData()
      }

    },
    _tableBind() {
      const defaultAttr = _.pick(this, [
        'size', 'width',
        'maxHeight', 'fit', 'stripe', 'border',
        'rowKey', 'context', 'showHeader',
        'showSummary', 'sumText', 'summaryMethod',
        'rowClassName', 'rowStyle', 'cellClassName',
        'cellStyle', 'headerRowClassName', 'headerRowStyle',
        'headerCellClassName', 'headerCellStyle', 'highlightCurrentRow',
        'currentRowKey', 'emptyText', 'expandRowKeys',
        'defaultExpandAll', 'defaultSort', 'tooltipEffect',
        'spanMethod', 'selectOnIndeterminate', 'indent',
        'treeProps', 'lazy', 'load',

      ])
      return Object.assign({ height: this.autoFlex ? 'auto' : this.caculateTableHeight }, defaultAttr, this.$attrs)
    }
  },
  props: {
    data: {
      type: Array,
      default: function () {
        return [];
      }
    },
    size: String,
    width: [String, Number],
    height: [String, Number],
    maxHeight: [String, Number],
    fit: {
      type: Boolean,
      default: true
    },
    stripe: Boolean,
    border: {
      type: Boolean,
      default: true
    },
    rowKey: [String, Function],
    context: {},
    showHeader: {
      type: Boolean,
      default: true
    },
    showSummary: Boolean,
    sumText: String,
    summaryMethod: Function,
    rowClassName: [String, Function],
    rowStyle: [Object, Function],
    cellClassName: [String, Function],
    cellStyle: [Object, Function],
    headerRowClassName: [String, Function],
    headerRowStyle: [Object, Function],
    headerCellClassName: [String, Function],
    headerCellStyle: [Object, Function],
    highlightCurrentRow: Boolean,
    currentRowKey: [String, Number],
    emptyText: String,
    expandRowKeys: Array,
    defaultExpandAll: Boolean,
    defaultSort: Object,
    tooltipEffect: String,
    spanMethod: Function,
    selectOnIndeterminate: {
      type: Boolean,
      default: true
    },
    indent: {
      type: Number,
      default: 16
    },
    treeProps: {
      type: Object,
      default() {
        return {
          hasChildren: 'hasChildren',
          children: 'children'
        };
      }
    },
    lazy: Boolean,
    load: Function,


    pageChangeBefore: {
      type: Function,
      default: null,
    },
    defaultPageSize: {
      type: Number,
      default: 20
    },


    defaultSortColumn: {
      type: String,
      default: '_blank_'
    },




    simplePage: {
      type: Boolean,
      default: false
    },
    autoLoad: {
      type: Boolean,
      default: true
    },
    url: '',
    rowIndexField: {
      type: String,
      default: '_row_index_'
    },
    autoPage: {
      type: Boolean,
      default: false
    },
    autoFill: {
      type: Boolean,
      default: false
    },
    autoFlex: {
      type: Boolean,
      default: false
    },
    emptySlot: {
      type: Boolean,
      default: true
    },
    urlDataHandle: Function,//用于处理，url返回值非正常状态的情况
    urlParams: {
      type: [Object, Function],
      default: () => { return {} },
    },
    urlOption: {
      type: [Object],
      default: () => {
        return {
          method: 'post'
        }
      },
    },
    tableVisible: {
      type: Boolean,
      default: true,
    },
  }
}

</script>
<style scoped>
.table-div {
  display: flex;
  flex-direction: column;

}

.table-flex {
  flex: 1 1 0
}
</style>
